package com.yn.pet.controller.app.biz;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yn.common.utils.DateUtils;
import com.yn.common.utils.StringUtils;
import com.yn.pet.bus.entity.DeviceInfo;
import com.yn.pet.bus.entity.DeviceSim;
import com.yn.pet.bus.entity.DeviceSyncSettings;
import com.yn.pet.bus.entity.LocationRealtime;
import com.yn.pet.bus.enums.DeviceStatusEnum;
import com.yn.pet.controller.pc.request.AlarmUpdateRequest;
import com.yn.pet.controller.pc.response.AlarmListResponse;
import com.yn.pet.controller.pc.response.LocationModelInfoResponse;
import com.yn.pet.controller.pc.response.MileageCountResponse;
import com.yn.pet.controller.tcpserver.PetServer808Service;
import com.yn.pet.entity.T8103;
import com.yn.pet.enums.DeviceModelEnum;
import com.yn.pet.protocol.t808.T0001;


import com.yn.pet.protocol.t808.T8105;
import com.yn.pet.protocol.t808.T8401;
import com.yn.pet.service.*;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.nio.charset.Charset;
import java.util.*;

@Service
@RequiredArgsConstructor
@Slf4j
public class ASettingsBizService {

    private final DeviceSyncSettingsService deviceSyncSettingsService;

    private final DeviceSimService deviceSimService;

    private final PetServer808Service petServer808Service;

    private final LocationRealtimeService locationRealtimeService;

    private final GenFenceAlarmService  genFenceAlarmService;

    private final AlarmRecordService alarmRecordService;

    private final DeviceInfoService deviceInfoService;




    /**
     * 获取设备报警信息
     *
     * @param deviceId 设备ID
     * @return DeviceSyncSettings
     */
    public AlarmListResponse getAlarmInfo(Long deviceId) {

        DeviceSyncSettings settings = deviceSyncSettingsService.getInfoByDeviceId(deviceId);
        if(settings==null){
            return null;
        }

        return AlarmListResponse.transform(settings);
    }

    /**
     * 更新设备报警信息
     * @param request 报警信息
     * @return
     */
    public void updateAlarm(AlarmUpdateRequest request) {

        LambdaUpdateWrapper<DeviceSyncSettings> wrapper = Wrappers.lambdaUpdate();

        wrapper.eq(DeviceSyncSettings::getId, request.getId());
        wrapper.set(Objects.nonNull(request.getFenceEnabled()),DeviceSyncSettings::getFenceEnabled, request.getFenceEnabled())
                .set(Objects.nonNull(request.getOfflineEnabled()),DeviceSyncSettings::getOfflineEnabled, request.getOfflineEnabled())
                .set(Objects.nonNull(request.getLowBatteryEnabled()),DeviceSyncSettings::getLowBatteryEnabled, request.getLowBatteryEnabled())
                .set(Objects.nonNull(request.getVibrationEnabled()),DeviceSyncSettings::getVibrationEnabled, request.getVibrationEnabled());
        deviceSyncSettingsService.update(wrapper);
    }

    /**
     * 一键重启
     * @param deviceId 设备id
     */
    public void reboot(Long deviceId) {
        //根据设备id查询设备sim卡表信息
        /*DeviceSim deviceSim = deviceSimService.getByDeviceId(deviceId);
        if(deviceSim == null){
            throw new RuntimeException("设备sim卡信息不存在");
        }
        String clientId = deviceSim.getPhoneNumber();*/
        //获取设备信息，如果设备不在线返回错误信息
        LambdaQueryWrapper<DeviceInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DeviceInfo::getDeviceId, deviceId);
        DeviceInfo deviceInfo = deviceInfoService.getOne(wrapper);
        if(deviceInfo == null){
            throw new RuntimeException("设备信息不存在");
        }
        if(Objects.equals(deviceInfo.getDeviceStatus(), DeviceStatusEnum.OFFLINE.getCode())){
            throw new RuntimeException("设备不在线");
        }

        String clientId = deviceInfo.getImei();
        sendCommand2T8105(clientId, 4);
    }

    /**
     * 恢复出厂设置
     * @param deviceId 设备id
     */
    public void RestoreFactorySettings(Long deviceId){
        if(deviceId == null){
           throw new RuntimeException("设备ID不能为空");
        }
        //根据设备id查询设备sim卡表信息
        /*DeviceSim deviceSim = deviceSimService.getByDeviceId(deviceId);
        if(deviceSim == null){
            throw new RuntimeException("设备sim卡信息不存在");
        }
        String clientId = deviceSim.getPhoneNumber();*/
        LambdaQueryWrapper<DeviceInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DeviceInfo::getDeviceId, deviceId);
        DeviceInfo deviceInfo = deviceInfoService.getOne(wrapper);
        if(deviceInfo == null){
            throw new RuntimeException("设备信息不存在");
        }
        String clientId = deviceInfo.getImei();
        sendCommand2T8105(clientId, 5);
    }

    /**
     * 一键关机
     * @param deviceId 设备ID
     */
    public void ShutDown(Long deviceId){
        if(deviceId == null){
            throw new RuntimeException("设备ID不能为空");
        }
        //根据设备id查询设备sim卡表信息
      /*  DeviceSim deviceSim = deviceSimService.getByDeviceId(deviceId);
        if(deviceSim == null){
            throw new RuntimeException("设备sim卡信息不存在");
        }
        String clientId = deviceSim.getPhoneNumber();*/
        LambdaQueryWrapper<DeviceInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DeviceInfo::getDeviceId, deviceId);
        DeviceInfo deviceInfo = deviceInfoService.getOne(wrapper);
        if(deviceInfo == null){
            throw new RuntimeException("设备信息不存在");
        }
        String clientId = deviceInfo.getImei();
        sendCommand2T8105(clientId, 3);
    }

   public void sendCommand2T8105(String clientId, Integer command){
       T8105 t8105 = new T8105();
       t8105.setClientId(clientId);
       t8105.setCommand(command);
       t8105.setParameter("");
       log.info("T8105 发送命令: {}", t8105);
       petServer808Service.T8105(t8105)
               .doOnSuccess(apiResult -> {
                   if (apiResult != null && apiResult.getData() != null) {
                       T0001 response = apiResult.getData();
                       if (response.getResultCode() == 0 && Boolean.TRUE.equals(response.isSuccess())) {
                           log.info("消息接收成功");
                       } else {
                           log.error("消息接收失败，状态码: {}", response.getResultCode());
                           throw new RuntimeException("消息接收失败");
                       }
                   }else{
                       //走熔断了
                       log.error("发送消息走熔断了，clientId：{}", clientId);
                       //throw new RuntimeException("网络异常，请稍后重试");
                   }
               })
               .doOnError(throwable -> {
                   log.error("发送消息失败，clientId：{}",  clientId,throwable);
                   throw new RuntimeException("网络异常，请稍后重试");
               })
               .subscribe(
                       result -> log.info("发送成功"),
                       throwable -> {
                           // 这里才是最终的错误处理入口
                           log.error("订阅失败", throwable);
                           // 可再次更新状态或做其他处理
                       }
               );
   }

    /**
     * 获取定位模式信息
     * @param deviceId 设备ID
     * @return
     */
    public LocationModelInfoResponse getLocationModelInfo(Long deviceId) {
        DeviceSyncSettings settings = deviceSyncSettingsService.getInfoByDeviceId(deviceId);
        if (settings == null) {
            return null;
        }
        LocationModelInfoResponse response = new LocationModelInfoResponse();
        response.setDeviceModel(settings.getDeviceModel());
        response.setDeviceModelName(DeviceModelEnum.getByCode(settings.getDeviceModel()).getName());
        //如果是省电模式
        if(Objects.equals(settings.getDeviceModel(), DeviceModelEnum.POWER_SAVING.getCode())){
            int minutes = settings.getGpsTimingInterval() / 60;
            response.setGpsTimingInterval(minutes+"");
        }
        return response;
    }


    public void updateLocationModel(Long deviceId, Integer type,String minutes) {
        //从数据库里获取设备的在线状态，如果离线，直接报错
        LambdaQueryWrapper<DeviceInfo> wrapper1 = Wrappers.lambdaQuery();
        wrapper1.eq(DeviceInfo::getDeviceId, deviceId);
        DeviceInfo deviceInfo = deviceInfoService.getOne(wrapper1);
        if(deviceInfo == null){
            throw new RuntimeException("设备信息不存在");
        }
        if(Objects.equals(deviceInfo.getDeviceStatus(), DeviceStatusEnum.OFFLINE.getCode())){
            throw new RuntimeException("设备已离线,无法修改定位模式");
        }

        //判断传入的枚举值是否合法
        DeviceModelEnum code = DeviceModelEnum.getByCode(type);
        if (code == null) {
            throw new RuntimeException("定位模式类型错误");
        }
        LambdaUpdateWrapper<DeviceSyncSettings> wrapper = Wrappers.lambdaUpdate();

        wrapper.eq(DeviceSyncSettings::getDeviceId, deviceId);
        wrapper.set(DeviceSyncSettings::getDeviceModel, code.getCode());
        //如果是耗电模式
        if(Objects.equals(type, DeviceModelEnum.POWER_CONSUMPTION.getCode())){
            wrapper.set(DeviceSyncSettings::getGpsTimingEnabled, 1);
            wrapper.set(DeviceSyncSettings::getGpsTimingInterval, null);

        }else if(Objects.equals(type, DeviceModelEnum.POWER_SAVING.getCode())){
            //如果是省电模式
            if(StringUtils.isEmpty(minutes) || Integer.parseInt(minutes) < 1 || Integer.parseInt(minutes) > 1080){
                throw new RuntimeException("省电模式时间输入错误");
            }else{
                //将string转为整数
                int minutesInt = Integer.parseInt(minutes);
                //分钟转为秒
                int minutesFinal = minutesInt*60;
                wrapper.set(DeviceSyncSettings::getGpsTimingEnabled, 1);
                wrapper.set(DeviceSyncSettings::getGpsTimingInterval, minutesFinal);
            }
        }else if(Objects.equals(type, DeviceModelEnum.SUPER_POWER_SAVING.getCode())){
            //如果是超级省电模式
            wrapper.set(DeviceSyncSettings::getGpsTimingEnabled, 0);
            wrapper.set(DeviceSyncSettings::getGpsTimingInterval, null);
        }

        //发送消息给设备
        deviceSyncSettingsService.update(wrapper);

        //根据设备id查询sim卡表信息
       /* DeviceSim deviceSim = deviceSimService.getByDeviceId(deviceId);
        if(deviceSim == null){
            throw new RuntimeException("设备sim卡信息不存在");
        }
        String clientId = deviceSim.getPhoneNumber();*/
        String clientId = deviceInfo.getImei();
        int total = 1;
        T8103 t8103 = new T8103();
        t8103.setClientId(clientId);
        t8103.setTotal(total);
        Map<Integer, Integer> map = new HashMap<>();
        if (type.equals(DeviceModelEnum.POWER_CONSUMPTION.getCode())) {
            //模式1: 010000的十六进制
            map.put(61729, hexToDecimal("01" + toFourDigitHex(0)));
        } else if (type.equals(DeviceModelEnum.POWER_SAVING.getCode())) {
            //模式7：07xxxx的十六进制 xxxx为传入的时间间隔的十六进制 eg:30s -> 001E
            map.put(61729, hexToDecimal("07" + toFourDigitHex(Integer.parseInt(minutes) * 60)));
        } else if (type.equals(DeviceModelEnum.SUPER_POWER_SAVING.getCode())) {
            //模式8：080000的十六进制：
            map.put(61729, hexToDecimal("08" + toFourDigitHex(0)));
        }
        t8103.setParametersInt(map);
        t8103.build();
        petServer808Service.T8103(t8103)
                .doOnSuccess(apiResult -> {
                    if (apiResult != null && apiResult.getData() != null) {
                        T0001 response = apiResult.getData();
                        if (response.getResultCode() == 0 && Boolean.TRUE.equals(response.isSuccess())) {
                            log.info("消息接收成功");
                        } else {

                            log.error("消息接收失败，状态码: {}", response.getResultCode());
                            //throw new RuntimeException("消息接收失败");
                        }
                    }else{
                        //走熔断了
                        log.error("发送T8600消息走熔断了，设备id：{}", deviceId);
                        //throw new RuntimeException("网络异常，请稍后重试");
                    }
                })
                .doOnError(throwable -> {
                    log.error("发送T8103消息失败，设备ID：{}",  deviceId,throwable);
                    throw new RuntimeException("网络异常，请稍后重试");
                })
                .subscribe(
                        result -> log.info("发送成功"),
                        throwable -> {
                            // 这里才是最终的错误处理入口
                            log.error("订阅失败", throwable);
                            // 可再次更新状态或做其他处理
                        }
                );
    }

    /**
     * 获取设备里程统计
     * @param deviceId 设备id
     * @param startTime 开始时间
     * @param endTime 结束区间
     * @return MileageCountResponse
     */
    public MileageCountResponse getMileageCount(Long deviceId, Date startTime, Date endTime) {
       if(startTime == null || endTime == null){
           startTime = DateUtils.getTodayStart();
           endTime = DateUtils.getTodayEnd();
           return findMileageCount(deviceId, startTime, endTime, 1);
       }else{
           long number = DateUtils.daysBetween(startTime, endTime);
           return findMileageCount(deviceId, startTime, endTime, (int) number+1);
       }
    }

    /**
     * 获取某段时间的设备里程统计
     * @param deviceId 设备id
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param number 初始时间和结束时间的差值
     * @return MileageCountResponse
     */
    public MileageCountResponse findMileageCount(Long deviceId, Date startTime,Date endTime, int number){
        Double totalMileage=0.0;

        Date beginTime=startTime;
        for(int i = 0; i < number; i++){
            //获取今天时间
            startTime = DateUtils.parseDayStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTime));
            //位置表获取总里程
            List<LocationRealtime> dayLocation = locationRealtimeService.listOneDayLocation(startTime, deviceId);
            //集合非空，存数据，空的话不管
            if(!CollectionUtils.isEmpty(dayLocation)){
                totalMileage+=dayLocation.get(0).getMileage();
            }
            startTime = DateUtils.addDays(startTime, 1);
        }
        //根据设备id查询栏目警告记录表得到栏目警告记录次数
        Long fenceAlarmCount = genFenceAlarmService.getCountByDeviceId(deviceId, beginTime, endTime);
        if(fenceAlarmCount==null){
            fenceAlarmCount=0L;
        }
        //根据设备id查询其他警告记录表得到警告记录次数
        Long otherAlarmCount = alarmRecordService.getCountByDeviceId(deviceId, beginTime, endTime);
        if(otherAlarmCount==null){
            otherAlarmCount=0L;
        }
        Integer alarmCount = (int) (fenceAlarmCount+otherAlarmCount);

        MileageCountResponse response = new MileageCountResponse();
        response.setDeviceId(deviceId);
        response.setTotalMileage(totalMileage);
        response.setAlarmCount(alarmCount);
        return response;
    }
    /**
     * 将十进制数字转换为四位十六进制字符串（大写）
     *
     * @param decimal 十进制数字
     * @return 四位十六进制字符串，不足四位前面补0
     */
    public static String toFourDigitHex(int decimal) {
        return String.format("%04X", decimal);
    }
    /**
     * 将六位十六进制字符串转换为十进制数字
     *
     * @param hex 六位十六进制字符串（如"010000"）
     * @return 十进制数字
     * @throws NumberFormatException 如果输入的不是有效的十六进制字符串
     */
    public static int hexToDecimal(String hex) {
        // 去掉可能存在的"0x"前缀
        if (hex.startsWith("0x") || hex.startsWith("0X")) {
            hex = hex.substring(2);
        }

        // 确保是6位长度
        /*if (hex.length() != 6) {
            throw new IllegalArgumentException("输入必须是6位十六进制数");
        }*/

        // 转换为十进制
        return Integer.parseInt(hex, 16);
    }

    public static void main(String[] args) {
        //70分钟
        int decimal = 60*10;
        String hex = toFourDigitHex(decimal);

        int hex2 = hexToDecimal("07"+toFourDigitHex(600));
        System.out.println(hex);
        System.out.println(hex2);
        System.out.println(hexToDecimal("07" + toFourDigitHex(Integer.parseInt("10") * 60)));
    }

    public void addConcat(Integer sign, String phoneNumber, String name) {
        String clientId="21210047094";
        T8401 t8401 = new T8401();
        t8401.setClientId(clientId);
        t8401.setType(2);
        List<T8401.Contact> contacts=new ArrayList<>();
        contacts.add(new T8401.Contact(sign, phoneNumber, name));
        t8401.setContacts( contacts);
        petServer808Service.T8401( t8401).doOnSuccess(apiResult -> {
                    if (apiResult != null && apiResult.getData() != null) {
                        T0001 response = apiResult.getData();
                        if (response.getResultCode() == 0 && Boolean.TRUE.equals(response.isSuccess())) {
                            log.info("消息接收成功");
                        } else {

                            log.error("消息接收失败，状态码: {}", response.getResultCode());
                            //throw new RuntimeException("消息接收失败");
                        }
                    }else{
                        //走熔断了
                        log.error("发送消息走熔断了,设置联系人白名单4");
                        //throw new RuntimeException("网络异常，请稍后重试");
                    }
                })
                .doOnError(throwable -> {
                    log.error("发送消息失败，设置联系人白名单");
                    throw new RuntimeException("网络异常，请稍后重试");
                })
                .subscribe(
                        result -> log.info("发送成功，设置联系人白名单4"),
                        throwable -> {
                            // 这里才是最终的错误处理入口
                            log.error("订阅失败，设置联系人白名单", throwable);
                            // 可再次更新状态或做其他处理
                        }
                );
    }

    public void setHeartbeatTime(Integer time, String imei) {
        int total = 1;
        T8103 t8103 = new T8103();
        t8103.setClientId(imei);
        t8103.setTotal(total);
        Map<Integer, Integer> map = new HashMap<>();
        map.put(1,time);
        t8103.setParametersInt(map);
        t8103.build();
        petServer808Service.T8103(t8103)
                .doOnSuccess(apiResult -> {
                    if (apiResult != null && apiResult.getData() != null) {
                        T0001 response = apiResult.getData();
                        if (response.getResultCode() == 0 && Boolean.TRUE.equals(response.isSuccess())) {
                            log.info("消息接收成功");
                        } else {

                            log.error("消息接收失败，状态码: {}", response.getResultCode());
                            //throw new RuntimeException("消息接收失败");
                        }
                    }else{
                        //走熔断了
                        log.error("发送消息走熔断了，设备mei：{}", imei);
                        //throw new RuntimeException("网络异常，请稍后重试");
                    }
                })
                .doOnError(throwable -> {
                    log.error("发送T8103消息失败，设备imei：{}",  imei,throwable);
                    throw new RuntimeException("网络异常，请稍后重试");
                })
                .subscribe(
                        result -> log.info("发送成功"),
                        throwable -> {
                            // 这里才是最终的错误处理入口
                            log.error("订阅失败", throwable);
                            // 可再次更新状态或做其他处理
                        }
                );
    }
}
